<template>
  <div class="demo-section">
    <h3 class="section-title">虚拟滚动优化</h3>
    <div class="demo-description">
      <p>虚拟滚动技术只渲染可视区域内的列表项，对于大型数据集可以显著减少 DOM 节点数量和提升渲染性能。</p>
      <p>本示例实现了一个简易的虚拟滚动组件，适用于长列表场景。</p>
    </div>
    <div class="demo-actions">
      <div class="action-group">
        <button @click="generateLargeList" class="btn btn-primary">
          生成 {{ listSize }} 条数据
        </button>
        <select v-model="listSize" class="form-input">
          <option value="1000">1,000 条</option>
          <option value="10000">10,000 条</option>
          <option value="100000">100,000 条</option>
        </select>
      </div>
      <div class="action-group">
        <button @click="toggleVirtualScroll" class="btn btn-secondary">
          {{ useVirtualScroll ? '禁用' : '启用' }} 虚拟滚动
        </button>
      </div>
    </div>
    <div class="performance-stats">
      <div class="stat-item">
        <span class="stat-label">数据总量:</span>
        <span class="stat-value">{{ virtualScrollData.length.toLocaleString() }}</span>
      </div>
      <div class="stat-item">
        <span class="stat-label">渲染项数量:</span>
        <span class="stat-value">{{ renderedItemsCount }}</span>
      </div>
      <div class="stat-item">
        <span class="stat-label">滚动位置:</span>
        <span class="stat-value">{{ scrollPosition }}px</span>
      </div>
      <div class="stat-item">
        <span class="stat-label">性能模式:</span>
        <span class="stat-value" :class="{ optimized: useVirtualScroll }">
          {{ useVirtualScroll ? '虚拟滚动优化' : '普通渲染' }}
        </span>
      </div>
    </div>
    <div class="component-display">
      <div class="virtual-scroll-container">
        <div 
          v-if="useVirtualScroll"
          class="virtual-scroll-wrapper"
          @scroll="handleScroll"
          ref="virtualScrollContainer"
        >
          <div 
            class="virtual-scroll-content"
            :style="{ height: totalHeight + 'px' }"
          >
            <div 
              class="virtual-scroll-offset"
              :style="{ transform: `${TRANSFORM_PREFIX}(${offsetY}px)` }"
            >
              <div 
                v-for="item in visibleItems" 
                :key="item.id"
                class="virtual-scroll-item"
              >
                <div class="item-id">#{{ item.id }}</div>
                <div class="item-content">
                  <div class="item-title">项目 {{ item.id }}</div>
                  <div class="item-description">描述内容: {{ item.description }}</div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div 
          v-else
          class="regular-scroll-container"
          @scroll="handleRegularScroll"
          ref="regularScrollContainer"
        >
          <div 
            v-for="item in visibleItems" 
            :key="item.id"
            class="virtual-scroll-item"
          >
            <div class="item-id">#{{ item.id }}</div>
            <div class="item-content">
              <div class="item-title">项目 {{ item.id }}</div>
              <div class="item-description">描述内容: {{ item.description }}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="code-sample">
      <h4>虚拟滚动核心原理</h4>
      <pre>// 提取的常量
const BUFFER_ITEM_COUNT = 2; // 多渲染的缓冲项数量
const TRANSFORM_PREFIX = 'translateY';

// 1. 监听滚动事件
const handleScroll = () => {
  const scrollTop = scrollContainer.scrollTop;
  
  // 2. 计算当前可见区域的起始索引
  const startIndex = Math.floor(scrollTop / itemHeight);
  
  // 3. 计算需要渲染的项数量
  const visibleCount = Math.ceil(containerHeight / itemHeight) + BUFFER_ITEM_COUNT;
  
  // 4. 获取可见的数据项
  visibleItems.value = data.slice(startIndex, startIndex + visibleCount);
  
  // 5. 设置偏移量
  offsetY.value = startIndex * itemHeight;
};

// 6. 使用 transform 定位可见项
&lt;div 
  class="virtual-scroll-offset"
  :style="{ transform: `${TRANSFORM_PREFIX}(${offsetY}px)` }"
&gt;
  &lt;div v-for="item in visibleItems" :key="item.id"&gt;
    {{ item.content }}
  &lt;/div&gt;
&lt;/div&gt;</pre>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue';

// 常量定义
const BUFFER_ITEM_COUNT = 2; // 多渲染的缓冲项数量
const TRANSFORM_PREFIX = 'translateY';

// 响应式数据
const virtualScrollData = ref([]);
const listSize = ref(1000);
const useVirtualScroll = ref(true);
const scrollPosition = ref(0);
const renderedItemsCount = ref(0);
const virtualScrollContainer = ref(null);
const regularScrollContainer = ref(null);

// 虚拟滚动配置
const itemHeight = 80;
const containerHeight = 400;
const visibleCount = Math.ceil(containerHeight / itemHeight) + BUFFER_ITEM_COUNT;
const startIndex = ref(0);
const offsetY = ref(0);

// 计算属性
const totalHeight = computed(() => virtualScrollData.value.length * itemHeight);

const visibleItems = computed(() => {
  if (useVirtualScroll.value) {
    const endIndex = Math.min(startIndex.value + visibleCount, virtualScrollData.value.length);
    return virtualScrollData.value.slice(startIndex.value, endIndex);
  }
  return virtualScrollData.value;
});

// 方法
const generateLargeList = () => {
  const size = parseInt(listSize.value);
  virtualScrollData.value = Array.from({ length: size }, (_, index) => ({
    id: index + 1,
    description: `这是项目 ${index + 1} 的详细描述信息，包含了一些示例文本内容。`
  }));
  startIndex.value = 0;
  offsetY.value = 0;
};

const toggleVirtualScroll = () => {
  useVirtualScroll.value = !useVirtualScroll.value;
};

const handleScroll = () => {
  if (!virtualScrollContainer.value) return;
  const scrollTop = virtualScrollContainer.value.scrollTop;
  scrollPosition.value = scrollTop;
  startIndex.value = Math.floor(scrollTop / itemHeight);
  offsetY.value = startIndex.value * itemHeight;
  renderedItemsCount.value = visibleItems.value.length;
};

const handleRegularScroll = () => {
  if (!regularScrollContainer.value) return;
  scrollPosition.value = regularScrollContainer.value.scrollTop;
  renderedItemsCount.value = visibleItems.value.length;
};

// 生命周期
onMounted(() => {
  generateLargeList();
});
</script>

<style scoped>
.demo-section {
  animation: fadeIn 0.3s ease;
}

.virtual-scroll-wrapper {
  height: 400px;
  overflow-y: auto;
  border: 1px solid #e5e7eb;
  border-radius: 0.5rem;
  position: relative;
}

.virtual-scroll-content {
  position: relative;
  width: 100%;
}

.virtual-scroll-offset {
  width: 100%;
}

.virtual-scroll-item {
  height: 80px;
  padding: 1rem;
  border-bottom: 1px solid #e5e7eb;
  display: flex;
  align-items: center;
  gap: 1rem;
}

.item-id {
  font-weight: bold;
  color: #6366f1;
  min-width: 40px;
}

.item-content {
  flex: 1;
}

.item-title {
  font-weight: 600;
  margin-bottom: 0.25rem;
}

.item-description {
  color: #6b7280;
  font-size: 0.875rem;
}

.regular-scroll-container {
  height: 400px;
  overflow-y: auto;
  border: 1px solid #e5e7eb;
  border-radius: 0.5rem;
}

.stat-value.optimized {
  color: #10b981;
  font-weight: 600;
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
</style>